package com.saturday.utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @类名称 校验工具类
 * @类描述 <pre>校验工具类</pre>
 */
public class RegexUtil {

    private static final String REGEX_PWD = "^[a-zA-Z]\\w{6,12}$";

    private static final String REGEX_EMAIL = "^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";

    private static final String REGEX_RIGHTFUL = "^[A-Za-z0-9_-]+$";

    private static final String REGEX_LETTER_NUMBER_UNDERLINE = "^[A-Za-z0-9_]+$";

    private static final String REGEX_NUMBER = "^[-+]?[0-9]*[\\.]?[0-9]*$";

    private static final String REGEX_INT = "^[-]{0,1}[0-9]{1,}$";

    private static final String REGEX_MOBILE = "^1[3|4|5|7|8][0-9]\\d{8}$";

    private static final String REGEX_TEL = "^0\\d{2,3}-?\\d{7,8}$";

    private static final String REGEX_USERNAME = "^[a-zA-Z][a-zA-Z0-9]{3,15}$";

    private static final String REGEX_DECIMALS = "^\\d+(\\.\\d{1,2})?$";

    private static final String REGEX_IPV4 = "\\\\b((?!\\\\d\\\\d\\\\d)\\\\d+|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])\\\\.((?!\\\\d\\\\d\\\\d)\\\\d+|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])\\\\.((?!\\\\d\\\\d\\\\d)\\\\d+|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])\\\\.((?!\\\\d\\\\d\\\\d)\\\\d+|1\\\\d\\\\d|2[0-4]\\\\d|25[0-5])\\\\b";

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    /**
     * @param value
     * @return
     * @方法名称 isNull 是否为空
     * @功能描述 <pre></pre>
     * @作者
     */
    public final static boolean isNull(String value) {
        return StringUtils.isEmpty(value);
    }

    /**
     * @param value 值
     * @return 不为空返回true, 空返回false
     * @方法名称 isNotNull 不为空
     * @功能描述 <pre></pre>
     * @作者
     */
    public final static boolean isNotNull(String value) {
        return !isNull(value);
    }

    /**
     * @param str 校验字符串
     * @return 正确true, 失败false
     * @方法名称 isPwd
     * @功能描述 <pre>匹配密码，以字母开头，长度在6-12之间，只能包含字符、数字和下划线。</pre>
     * @作者
     */
    public final static boolean isPwd(String str) {
        return match(str, REGEX_PWD);
    }

    /**
     * @param str
     * @return
     * @方法名称 isNumber
     * @功能描述 <pre>匹配数字</pre>
     * @作者
     */
    public final static boolean isNumber(String str) {
        return match(str, REGEX_NUMBER);
    }

    /**
     * @param str
     * @return
     * @方法名称 isInteger
     * @功能描述 <pre>匹配整形数字</pre>
     * @作者
     */
    public final static boolean isInteger(String str) {
        return match(str, REGEX_INT);
    }

    /**
     * @param str 被校验字符串
     * @return 正确true, 失败false
     * @方法名称 isEmail
     * @功能描述 <pre>匹配Email地址</pre>
     * @作者
     */
    public final static boolean isEmail(String str) {
        return match(str, REGEX_EMAIL);
    }

    /**
     * @param text
     * @return
     * @方法名称 isPhone
     * @功能描述 <pre>联系电话(手机/电话皆可)验证  </pre>
     * @作者
     */
    public final static boolean isPhone(String text) {
        if (isMobile(text) || isTel(text)) {
            return true;
        }
        return false;
    }


    public final static boolean isIpv4(String text) {
        return match(text, REGEX_IPV4);
    }

    /**
     * @param text
     * @return
     * @方法名称 isTel
     * @功能描述 <pre>电话号码验证</pre>
     * @作者
     */
    public final static boolean isTel(String text) {
        return match(text, REGEX_TEL);
    }

    /**
     * @param text
     * @return
     * @方法名称 isMobile
     * @功能描述 <pre>手机号码验证</pre>
     * @作者
     */
    public final static boolean isMobile(String text) {
        if (text.length() != 11) {
            return false;
        }
        return match(text, REGEX_MOBILE);
    }

    /**
     * @param str
     * @return
     * @方法名称 isUserName
     * @功能描述 <pre>用户名校验</pre>
     * @作者
     */
    public final static boolean isUserName(String str) {
        return match(str, REGEX_USERNAME);
    }

    /**
     * @param text
     * @return
     * @方法名称 isRightfulString
     * @功能描述 <pre>判断是否为合法字符(a-zA-Z0-9-_)</pre>
     * @作者
     */
    public final static boolean isRightfulString(String text) {
        return match(text, REGEX_RIGHTFUL);
    }

    /**
     * @param str
     * @return
     * @方法名称 isDecimals
     * @功能描述 <pre>两位小数的数字类型</pre>
     * @作者
     */
    public final static boolean isDecimals(String str) {
        return match(str, REGEX_DECIMALS);
    }

    /**
     * @param str
     * @param dateFormat
     * @return
     * @方法名称 isDate
     * @功能描述 <pre>是否日期</pre>
     * @作者
     */
    public final static boolean isDate(String str, String dateFormat) {
        if (!isNotNull(dateFormat)) {
            dateFormat = DATE_FORMAT;
        }
        DateFormat formatter = new SimpleDateFormat(dateFormat);
        try {
            Date date = formatter.parse(str);
            return str.equals(formatter.format(date));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 正则表达式匹配
     *
     * @param text 待匹配的文本
     * @param reg  正则表达式
     * @return
     * @author jiqinlin
     */
    private final static boolean match(String text, String reg) {
        if (StringUtils.isEmpty(text) || StringUtils.isEmpty(reg)) {
            return false;
        }
        return Pattern.compile(reg).matcher(text).matches();
    }

    /**
     * 获得匹配的字符串
     *
     * @param regex      匹配的正则
     * @param content    被匹配的内容
     * @param groupIndex 匹配正则的分组序号
     * @return 匹配后得到的字符串，未匹配返回null
     */
    public static String get(String regex, String content, int groupIndex) {
        if (null == content || null == regex) {
            return null;
        }

        final Pattern pattern = get(regex, Pattern.DOTALL);
        return get(pattern, content, groupIndex);
    }

    /**
     * 获得匹配的字符串
     *
     * @param pattern    编译后的正则模式
     * @param content    被匹配的内容
     * @param groupIndex 匹配正则的分组序号
     * @return 匹配后得到的字符串，未匹配返回null
     */
    public static String get(Pattern pattern, String content, int groupIndex) {
        if (null == content || null == pattern) {
            return null;
        }

        final Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            return matcher.group(groupIndex);
        }
        return null;
    }

    /**
     * @param regex 正则表达式
     * @param flags 正则标识位集合 {@link Pattern}
     * @return {@link Pattern}
     */
    public static Pattern get(String regex, int flags) {
        Pattern pattern = Pattern.compile(regex, flags);
        return pattern;
    }

    /**
     * 取得内容中匹配的所有结果
     *
     * @param regex   正则
     * @param content 被查找的内容
     * @param group   正则的分组
     * @return 结果列表
     */
    public static List<String> findAll(String regex, String content, int group) {
        return findAll(regex, content, group, new ArrayList<>());
    }

    /**
     * 取得内容中匹配的所有结果
     *
     * @param <T>        集合类型
     * @param regex      正则
     * @param content    被查找的内容
     * @param group      正则的分组
     * @param collection 返回的集合类型
     * @return 结果集
     */
    public static <T extends Collection<String>> T findAll(String regex, String content, int group, T collection) {
        if (null == regex) {
            return null;
        }
        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
        return findAll(pattern, content, group, collection);
    }

    /**
     * 取得内容中匹配的所有结果
     *
     * @param pattern 编译后的正则模式
     * @param content 被查找的内容
     * @param group   正则的分组
     * @return 结果列表
     */
    public static List<String> findAll(Pattern pattern, String content, int group) {
        return findAll(pattern, content, group, new ArrayList<>());
    }

    /**
     * 取得内容中匹配的所有结果
     *
     * @param <T>        集合类型
     * @param pattern    编译后的正则模式
     * @param content    被查找的内容
     * @param group      正则的分组
     * @param collection 返回的集合类型
     * @return 结果集
     */
    public static <T extends Collection<String>> T findAll(Pattern pattern, String content, int group, T collection) {
        if (null == pattern || null == content) {
            return null;
        }

        if (null == collection) {
            throw new NullPointerException("Null collection param provided!");
        }

        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            collection.add(matcher.group(group));
        }
        return collection;
    }

    /**
     * 计算指定字符串中，匹配pattern的个数
     *
     * @param regex   正则表达式
     * @param content 被查找的内容
     * @return 匹配个数
     */
    public static int count(String regex, String content) {
        if (null == regex) {
            return 0;
        }

        final Pattern pattern = get(regex, Pattern.DOTALL);
        return count(pattern, content);
    }

    /**
     * 计算指定字符串中，匹配pattern的个数
     *
     * @param pattern 编译后的正则模式
     * @param content 被查找的内容
     * @return 匹配个数
     */
    public static int count(Pattern pattern, String content) {
        if (null == pattern || null == content) {
            return 0;
        }

        int count = 0;
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            count++;
        }

        return count;
    }

    /**
     * 检验是否只含 字母、数字、下划线
     *
     * @param text
     * @return
     */
    public final static boolean isNumberLetterUnderline(String text) {
        return match(text, REGEX_LETTER_NUMBER_UNDERLINE);
    }

}
